import redis
from django.conf import settings
import json
import logging
logger = logging.getLogger(__name__)
class RedisClient:
    """
    Redis客户端工具类
    用于处理与Redis相关的所有操作
    """
    _instance = None
    def __new__(cls):
        """
        单例模式，确保只创建一个Redis连接实例
        """
        if cls._instance is None:
            cls._instance = super(RedisClient, cls).__new__(cls)
            cls._instance._initialized = False
        return cls._instance
    def __init__(self):
        """
        初始化Redis连接
        如果已经初始化过，则不再重复初始化
        """
        if self._initialized:
            return
        try:
            self.redis_client = redis.Redis(
                host=settings.REDIS_HOST if hasattr(settings, 'REDIS_HOST') else 'localhost',
                port=settings.REDIS_PORT if hasattr(settings, 'REDIS_PORT') else 6379,
                db=settings.REDIS_DB if hasattr(settings, 'REDIS_DB') else 0,
                decode_responses=True,  # 自动将响应解码为字符串
                socket_timeout=5,  # 连接超时时间
                socket_connect_timeout=5  # 连接超时时间
            )
            self._initialized = True
            logger.info("Redis连接初始化成功")
        except Exception as e:
            logger.error(f"Redis连接初始化失败: {str(e)}")
            raise
    def set_key(self, key, value, expire=None):
        """
        设置键值对
        :param key: 键
        :param value: 值
        :param expire: 过期时间（秒）
        :return: bool
        """
        try:
            if isinstance(value, (dict, list)):
                value = json.dumps(value, ensure_ascii=False)
            self.redis_client.set(key, value)
            if expire:
                self.redis_client.expire(key, expire)
            return True
        except Exception as e:
            logger.error(f"设置键值对失败: {str(e)}")
            return False
    def get_key(self, key):
        """
        获取键值
        :param key: 键
        :return: 值
        """
        try:
            value = self.redis_client.get(key)
            if value is None:
                return None
            try:
                return json.loads(value)
            except:
                return value
        except Exception as e:
            logger.error(f"获取键值失败: {str(e)}")
            return None
    def delete_key(self, key):
        """
        删除键
        :param key: 键
        :return: bool
        """
        try:
            self.redis_client.delete(key)
            return True
        except Exception as e:
            logger.error(f"删除键失败: {str(e)}")
            return False
    def exists_key(self, key):
        """
        检查键是否存在
        :param key: 键
        :return: bool
        """
        try:
            return bool(self.redis_client.exists(key))
        except Exception as e:
            logger.error(f"检查键是否存在失败: {str(e)}")
            return False